延續昨天的實驗,我們弄不懂為什麼可以由Android USB Serial Port 成功傳送資料並控制 arduino 動作。
今天我們來瞭解一下,究竟什麼時候 arduino StandaFrimata 中定義arduino 會傳送資料回 host computer ....
下面這個 loop function 會是解答我們疑問的關鍵!
void loop()
{
byte pin, analogPin;
/* DIGITALREAD - as fast as possible, check for changes and output them to the
* FTDI buffer using Serial.print() */
checkDigitalInputs(); // 檢查我們的 Digital Input Value 要不要回傳給 host computer
/* SERIALREAD - processing incoming messagse as soon as possible, while still
* checking digital inputs. */
while(Firmata.available()) // 收 host computer 送過來的指令 / 並執行相對應的動作
Firmata.processInput();
/* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
* 60 bytes. use a timer to sending an event character every 4 ms to
* trigger the buffer to dump. */
// 檢查並回傳類比資料給 host computer
currentMillis = millis();
if (currentMillis - previousMillis > samplingInterval) {
previousMillis += samplingInterval;
/* ANALOGREAD - do all analogReads() at the configured sampling interval */
for(pin=0; pin<TOTAL_PINS; pin++) {
if (IS_PIN_ANALOG(pin) && pinConfig[pin] == ANALOG) {
analogPin = PIN_TO_ANALOG(pin);
if (analogInputsToReport & (1 << analogPin)) {
Firmata.sendAnalog(analogPin, analogRead(analogPin));
}
}
}
// report i2c data for all device with read continuous mode enabled
// 如果有用到 I2C ,這段才有作用,今天我們可以略過這邊
if (queryIndex > -1) {
for (byte i = 0; i < queryIndex + 1; i++) {
readAndReportData(query[i].addr, query[i].reg, query[i].bytes);
}
}
}
}
上面的 code 可以知道,arduino 是每個 loop 都會檢查並回傳資料給 host computer 的,但是他判斷是否回傳資料的依據是?
藉由下面的 checkdigitalinputs 可以看到,他是由 reportPINs[ ] 裡面的設定值決定的,而這個關鍵的參數,就是由 host computer 送出 {REPORT_DIGITAL & PIN , 0x01} 這組command 決定的。
void checkDigitalInputs(void)
{
/* Using non-looping code allows constants to be given to readPort().
* The compiler will apply substantial optimizations if the inputs
* to readPort() are compile-time constants. */
if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}
我們可以藉由 RealTerm: Serial/TCP Terminal http://sourceforge.net/projects/realterm/?source=typ_redirect
開啟 arduino 對應的 COM port 測試frimata protocol ,
送出 REPORT_VERSION (0xF9) 會收到 F9 02 03
送出 0xF4,0x0D,0x01,0x91,0x20,0x00 跟 0xF4,0x0D,0x01,0x91,0x00,0x00 就可以控制 PIN 13 LED 亮暗
而我們送出 REPORT_ANALOG : 0xC0,0x01,0xC1,0x01,0xC2,0x01,0xC3,0x01,0xC4,0x01,0xC5,0x01,0xC6,0x01,0xC7,0x01,0xC8,0x01,0xC9,0x01,0xCA,0x01,0xCB,0x01,0xCC,0x01,0xCE,0x01,0xCF,0x01
就會連續收到如下資料:ANALOG_MESSAGE = 0xE0; 代表數位腳位讀入資料
E3 33 00 E2 3D 00 E1 48 00 E0 4E 00 EB 2F 01 E9 00 00 E7 00 00 E6 00 00
E5 00 00 E4 17 00 E3 27 00 E2 2D 00 E1 34 00 E0 37 00 EB 13 01 E9 00 00
E7 00 00 E6 00 00 E5 00 00 E4 04 00 E3 07 00 E2 06 00 E1 0D 00 E0 0F 00
EB 0C 01 E9 00 00 E7 00 00 E6 00 00 E5 00 00 E4 0B 00 E3 15 00 E2 18 00
E1 1F 00 E0 21 00 EB 21 01 E9 00 00 E7 00 00 E6 00 00 E5 00 00 E4 0B 00
E3 16 00 E2 1A 00 E1 21 00 E0 23 00 EB 1C 01 E9 00 00 E7 00 00 E6 00 00
E5 00 00 E4 08 00 E3 10 00 E2 13 00 E1 19 00 E0 1B 00 EB 16 01 E9 00 00
E7 00 00 E6 00 00 E5 00 00 E4 0A 00 E3 17 00 E2 1F 00 E1 2B 00 E0 32 00
藉由上面簡單的測試,我們可以知道 arduino 何時會送出資料,何時判斷收到的指令。
所以是 android serial port 「接收端」的問題,跟 arduino frimata 無關
看來已經一步一步逼近問題核心了
我們明天見 :P